function B = CGP_precoder(H_eff, AoD_groups, groups, P_T, alpha)
% CGP_PRECODER 公共组处理基带预编码器（公式36-37）
%   输入：
%     H_eff: [K×b]有效信道矩阵
%     AoD_groups: [1×G]AoD支持区域结构体
%     groups: [K×1]用户分组向量
%     P_T: 总发射功率
%     alpha: 正则化参数
%   输出：
%     B: [b×K]基带预编码矩阵（动态块对角）

    % ========== 1. 参数验证 ==========
    [K, b] = size(H_eff);
    G = length(AoD_groups);
    if nargin < 5
        alpha = 1/K; % 默认正则化参数
    end
    
    % ========== 2. 识别公共组（Algorithm 3） ==========
    common_groups = identify_common_groups(AoD_groups);
    G_prime = length(common_groups);
    
    % ========== 3. 初始化块对角矩阵 ==========
    B = zeros(b, K);
    
    % ========== 4. 遍历公共组 ==========
    for gp = 1:G_prime
        % 4.1 获取公共组包含的用户组
        group_set = common_groups{gp};
        
        % 4.2 合并组内用户
        user_idx = [];
        for g = group_set
            user_idx = [user_idx; find(groups == g)];
        end
        K_gp = length(user_idx);
        
        % 4.3 提取合并有效信道
        H_gp = H_eff(user_idx, :);
        
        % 4.4 公共组RZF预编码（公式36）
        W_gp = inv(H_gp' * H_gp + K_gp * alpha * eye(b));
        B_gp = W_gp * H_gp';
        
        % 4.5 功率归一化（公式37）
        pow_gp = real(trace(H_gp * W_gp.^2 * H_gp'));
        epsilon_gp = sqrt(P_T * K_gp / K / pow_gp);
        B_gp = epsilon_gp * B_gp;
        
        % 4.6 填充到块对角位置
        B(:, user_idx) = B_gp;
    end
    
    % ========== 5. 动态结构验证 ==========
%     validate_dynamic_blocks(B, common_groups, groups);
end

%% ========== 子函数：公共组识别 ==========
function common_groups = identify_common_groups(AoD_groups)
    G = length(AoD_groups);
    common_groups = {};
    grouped = false(1, G);
    
    for g = 1:G
        if grouped(g), continue; end
        current_group = g;
        
        for p = g+1:G
            if grouped(p), continue; end
            
            % 检查AoD重叠（公式13）
            if check_AoD_overlap(AoD_groups(g), AoD_groups(p))
                current_group = [current_group, p];
                grouped(p) = true;
            end
        end
        
        common_groups{end+1} = current_group;
        grouped(g) = true;
    end
end

%% ========== 子函数：AoD重叠检查 ==========
function overlap = check_AoD_overlap(AoD1, AoD2)
    % 检查x轴重叠
    x_overlap = (AoD1.gamma_x_range(1) <= AoD2.gamma_x_range(2)) && ...
                (AoD1.gamma_x_range(2) >= AoD2.gamma_x_range(1));
    
    % 检查y轴重叠
    y_overlap = (AoD1.gamma_y_range(1) <= AoD2.gamma_y_range(2)) && ...
                (AoD1.gamma_y_range(2) >= AoD2.gamma_y_range(1));
    
    overlap = x_overlap || y_overlap;
end